package com.yiminer.jobs;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlImageInput;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.yiminer.to.User;
import com.yiminer.util.TimerUtil;

public class SubmitThread extends Thread {

	WebClient webClient;
	User user;

	public SubmitThread(User user) {
		this.user = user;
	}

	public void run() {
		webClient = new WebClient(BrowserVersion.CHROME);
		webClient.getOptions().setThrowExceptionOnScriptError(false);
		webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
		if (login()) {
			process();
		}
	}
	
	int loginCount = 0;
	int loginMax = 5;
	// If login fail try 5 times, then give up
	public boolean login() {
		HtmlPage loginPage = null, page2 = null;
		HtmlForm loginForm = null;
		HtmlTextInput usernameInput = null, passwordInput = null;
		HtmlImageInput loginSubmit = null;

		try {
			System.out.println("[" + user.getApplicatioId() + "]Start to login...");
			
			// Input username and password
			loginPage = webClient.getPage("https://www.immigration.govt.nz/secure/default.htm");
			loginForm = loginPage.getForms().get(0);
			usernameInput = loginForm.getInputByName("Footer:newFooter:loginControl:userNameTextBox");
			usernameInput.setValueAttribute(user.getUsername());
			passwordInput = loginForm.getInputByName("Footer:newFooter:loginControl:passwordTextBox");
			passwordInput.setValueAttribute(user.getPassword());
			loginSubmit = loginForm.getInputByName("Footer:newFooter:loginControl:loginImageButton");
			
			// Check login successfully
			page2 = (HtmlPage) loginSubmit.click();
			page2.getAnchorByHref("/Registration/LogOut.aspx");
			
			System.out.println("[" + user.getApplicatioId() + "]Login success.");
		} catch (Exception e) {
			loginPage = null; page2 = null;
			loginForm = null;
			usernameInput = null; passwordInput = null;
			loginSubmit = null;
			
			loginCount++;
			if (loginCount <= loginMax) {
				System.out.println("[" + user.getApplicatioId() + "]Login Failure, relogin: " + e);
				return login();
			}
			loginCount = 0;
		}
		
		return true;
	}

	public void submitAction(HtmlPage submitPage, Boolean firstTime)
			throws Exception {
		if (!firstTime) {
			// Every 5 seconds Submit
			// This can be defined in User table
			// TODO
			Thread.sleep(5000);
		}
		if (!TimerUtil.isTimeup()) {
			HtmlForm submitForm = submitPage.getForms().get(0);
			HtmlImageInput submitButton = submitForm.getInputByName("ctl00$ContentPlaceHolder1$submitImageButton");
			if (null != submitButton) {
				fillSubmitPageData(submitForm);
				System.out.println("[" + user.getApplicatioId() + "]Submit....");
				HtmlPage submitResPage = (HtmlPage) submitButton.click();
				// throw new Exception();
				// This exception is used to simulated any exception caused by
				// no response from server side
				submitAction(submitResPage, false);
			} else {
				user.setStatus(2);
				// Send Notification
				sendNotification("test");
			}
		}
	}

	public void processSubmit() throws Exception {
		HtmlPage submitPage = webClient.getPage("https://www.immigration.govt.nz/WorkingHoliday/Application/Submit.aspx?ApplicationId="
						+ user.getApplicatioId());
		submitAction(submitPage, true);
	}

	public void payAction(HtmlPage payPage, Boolean firstTime)
			throws Exception {
		if (!firstTime) {
			// Every 5 seconds Submit
			// This can be defined in User table
			// TODO
			Thread.sleep(5000);
		}
		if (!TimerUtil.isTimeup()) {
			HtmlForm payForm = payPage.getForms().get(0);
			HtmlTextInput payerName = payForm.getInputByName("ctl00$ContentPlaceHolder1$payorNameTextBox");
			payerName.setValueAttribute(user.getPayname());
			System.out.println("["+user.getApplicatioId()+"]Set pay name and try pay...");
			HtmlImageInput okButton = payForm.getInputByName("ctl00$ContentPlaceHolder1$okImageButton");
			if (null != okButton) {
				HtmlPage payChooseCardPage = (HtmlPage) okButton.click();
				HtmlForm payChooseCardForm = payChooseCardPage.getForms().get(0);
				Boolean a = payChooseCardForm.hasHtmlElementWithId("card_type_MASTERCARD");
				if(!a){
					System.out.println("["+user.getApplicatioId()+"]Pay is not avaible, retrying...");
					HtmlPage payAgainPage = webClient
							.getPage("https://www.immigration.govt.nz/PaymentGateway/OnLinePayment.aspx?SourceUrl=https://www.immigration.govt.nz/WorkingHoliday/Application/SubmitConfirmation.aspx?ApplicationId="+user.getApplicatioId()+"&ApplicationId="+user.getApplicatioId()+"&ProductId=2");
					payAction(payAgainPage,false);
				}else{
					HtmlImageInput masterCardImg = payChooseCardForm.getInputByName("card_type_MASTERCARD");
					System.out.println("["+user.getApplicatioId()+"]Chose Master Card...");
					//TODO Support both Visa and Master
					HtmlPage masterPayPage = (HtmlPage)masterCardImg.click();
					HtmlForm masterPayForm = masterPayPage.getForms().get(0);
					System.out.println("["+user.getApplicatioId()+"]Input Care number and csc code...");
					HtmlTextInput cardNo = masterPayForm
							.getInputByName("cardnumber");
					cardNo.setValueAttribute(user.getCardNo());
					HtmlTextInput cscCode = masterPayForm
							.getInputByName("cardverificationcode");
					cscCode.setValueAttribute(user.getCssCode());
					HtmlSelect expiryMonthSelect = (HtmlSelect) masterPayPage.getElementById("expirymonth");
					HtmlOption expiryMonthOption = expiryMonthSelect.getOptionByValue(user.getExpiryMonth());
					expiryMonthSelect.setSelectedAttribute(expiryMonthOption, true);
					
					HtmlSelect expiryYearSelect = (HtmlSelect) masterPayPage.getElementById("expiryyear");
					HtmlOption expiryYearOption = expiryYearSelect.getOptionByValue(user.getExpiryYear());
					expiryYearSelect.setSelectedAttribute(expiryYearOption, true);
					
					HtmlSubmitInput payNowButton = masterPayForm.getInputByName("pay_now");
					HtmlPage payResultPage = payNowButton.click();
					System.out.println("["+user.getApplicatioId()+"][============Pay Result===============]");
					System.out.println(payResultPage.asText());
					System.out.println("["+user.getApplicatioId()+"][============Pay Result===============]");
				}
			} else {
				user.setStatus(2);
				// Send Notification
				sendNotification("test");
			}
		}
	}
	
	
	public void processPay() throws Exception {
		HtmlPage payPage = webClient
				.getPage("https://www.immigration.govt.nz/PaymentGateway/OnLinePayment.aspx?SourceUrl=https://www.immigration.govt.nz/WorkingHoliday/Application/SubmitConfirmation.aspx?ApplicationId="+user.getApplicatioId()+"&ApplicationId="+user.getApplicatioId()+"&ProductId=2");
		payAction(payPage, true);

	}

	public void process() {
		// 1: Pending for Submit
		if (user.getStatus() == 1) {
			try {
				System.out.println("["+user.getApplicatioId()+"]Start to process submit.");
				processSubmit();
				System.out.println("["+user.getApplicatioId()+"]End to process submit.");
			} catch (Exception e) {
				// This exception is used to handle any server delay exception
				System.out.println("["+user.getApplicatioId()+"][Exception] Retry Submit");
				if (!TimerUtil.isTimeup()) {
					process();
				}
			}
		}
		
		// 2: Pending for Pay
		if(user.getStatus()==2){
			try {
				System.out.println("["+user.getApplicatioId()+"]Start to process pay.");
				processPay();
				System.out.println("["+user.getApplicatioId()+"]End to process pay.");
			} catch (Exception e) {
				// This exception is used to handle any server delay exception
				System.out.println("["+user.getApplicatioId()+"][Exception] Retry pay");
				if (!TimerUtil.isTimeup()) {
					//process();
				}
			}
		}
		
	}

	private void fillSubmitPageData(HtmlForm submitForm) {
		HtmlCheckBoxInput box1 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$falseStatementCheckBox");
		box1.setChecked(true);
		HtmlCheckBoxInput box2 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$notesCheckBox");
		box2.setChecked(true);
		HtmlCheckBoxInput box3 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$circumstancesCheckBox");
		box3.setChecked(true);
		HtmlCheckBoxInput box4 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$warrantsCheckBox");
		box4.setChecked(true);
		HtmlCheckBoxInput box5 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$informationCheckBox");
		box5.setChecked(true);
		HtmlCheckBoxInput box6 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$healthCheckBox");
		box6.setChecked(true);
		HtmlCheckBoxInput box7 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$adviceCheckBox");
		box7.setChecked(true);
		HtmlCheckBoxInput box8 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$registrationCheckBox");
		box8.setChecked(true);
		HtmlCheckBoxInput box9 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$entitlementCheckbox");
		box9.setChecked(true);
		HtmlCheckBoxInput box10 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$permitExpiryCheckBox");
		box10.setChecked(true);
		HtmlCheckBoxInput box11 = submitForm.getInputByName("ctl00$ContentPlaceHolder1$medicalInsuranceCheckBox");
		box11.setChecked(true);
	}

	private void sendNotification(String msg) {
		// TODO
		System.out.println(msg);
	}

}
